package com.loopstack.gprint.utils;


import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;

public class BitmapUtils {
    public BitmapUtils() {
    }

    public static byte[] addBytes(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;
    }

    public static Bitmap resizeImage(Bitmap bitmap, int w, int h) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float scaleWidth = (float)w / (float)width;
        float scaleHeight = (float)h / (float)height;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    public static Bitmap resizeImageAndRotation(Bitmap bitmap, int w, int h) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float scaleWidth = (float)w / (float)width;
        float scaleHeight = (float)h / (float)height;
        Matrix matrix = new Matrix();
        matrix.setScale(1.0F, -1.0F);
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    private static byte[] getBinaryzationBytes(Bitmap bitmap) {
        return getBinaryzationBytes(bitmap, 128, false);
    }

    private static byte[] getBinaryzationBytes(Bitmap bitmap, boolean reverse) {
        return getBinaryzationBytes(bitmap, 128, reverse);
    }

    private static byte[] getBinaryzationBytes(Bitmap bitmap, int threshold, boolean reverse) {
        if (bitmap == null) {
            return null;
        } else {
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            byte[] data = new byte[width * height];
            int[] pixels = new int[width * height];
            bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

            for(int i = 0; i < height; ++i) {
                for(int j = 0; j < width; ++j) {
                    int color = pixels[i * width + j];
                    int gray = (int)(0.299 * (double)((color & 16711680) >> 16) + 0.587 * (double)((color & '\uff00') >> 8) + 0.114 * (double)(color & 255));
                    byte y = (byte)(reverse ? 1 : 0);
                    byte n = (byte)(reverse ? 0 : 1);
                    data[i * width + j] = gray < threshold ? y : n;
                }
            }

            return data;
        }
    }

    public static byte[] getCompressedBinaryzationBytes(Bitmap bitmap) {
        return getCompressedBinaryzationBytes(bitmap, 128, false);
    }

    public static byte[] getCompressedBinaryzationBytes(Bitmap bitmap, boolean reverse) {
        return getCompressedBinaryzationBytes(bitmap, 128, reverse);
    }

    public static byte[] getCompressedBinaryzationBytes(Bitmap bitmap, int threshold, boolean reverse) {
        if (bitmap == null) {
            return null;
        } else {
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int lineBytes = (width - 1) / 8 + 1;
            byte[] data = new byte[lineBytes * height];
            byte[] imageBytes = getBinaryzationBytes(bitmap, threshold, reverse);

            for(int i = 0; i < height; ++i) {
                for(int j = 0; j < lineBytes; ++j) {
                    byte unit = 0;

                    for(int k = 0; k < 8; ++k) {
                        if ((j << 3) + k < width) {
                            byte pixel = imageBytes[i * width + (j << 3) + k];
                            unit = (byte)(unit | (pixel & 1) << 7 - k);
                        }
                    }

                    data[i * lineBytes + j] = unit;
                }
            }

            return data;
        }
    }

    public static Bitmap threshold(Bitmap img, boolean shake) {
        int height = img.getHeight();
        int width = img.getWidth();
        Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, img.getConfig());
        Canvas c = new Canvas(bmpGrayscale);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0.0F);
        ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
        paint.setColorFilter(f);
        c.drawBitmap(img, 0.0F, 0.0F, paint);
        width = bmpGrayscale.getWidth();
        height = bmpGrayscale.getHeight();
        int[] pixels = new int[width * height];
        bmpGrayscale.getPixels(pixels, 0, width, 0, 0, width, height);
        int[] gray = new int[height * width];

        int e;
        int i;
        int j;
        int g;
        for(e = 0; e < height; ++e) {
            for(i = 0; i < width; ++i) {
                j = pixels[width * e + i];
                g = (j & 16711680) >> 16;
                gray[width * e + i] = g;
            }
        }


        for(i = 0; i < height; ++i) {
            for(j = 0; j < width; ++j) {
                g = gray[width * i + j];
                if (g >= 128) {
                    pixels[width * i + j] = -1;
                    e = g - 255;
                } else {
                    pixels[width * i + j] = -16777216;
                    e = g - 0;
                }

                if (shake) {
                    if (j < width - 1 && i < height - 1) {
                        gray[width * i + j + 1] += 7 * e / 16;
                        gray[width * (i + 1) + j] += 5 * e / 16;
                        gray[width * (i + 1) + j + 1] += e / 16;
                        if (j > 0) {
                            gray[width * (i + 1) + j - 1] += 3 * e / 16;
                        }
                    } else if (j == width - 1 && i < height - 1) {
                        gray[width * (i + 1) + j] += 5 * e / 16;
                    } else if (j < width - 1 && i == height - 1) {
                        gray[width * i + j + 1] += 7 * e / 16;
                    }
                }
            }
        }

        Bitmap mBitmap = Bitmap.createBitmap(width, height, bmpGrayscale.getConfig());
        mBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return mBitmap;
    }

    public static Bitmap filter(Bitmap src) {
        int width = src.getWidth();
        int height = src.getHeight();
        int[] inPixels = new int[width * height];
        int[] outPixels = new int[width * height];
        src.getPixels(inPixels, 0, width, 0, 0, width, height);
        double redSum = 0.0;
        double greenSum = 0.0;
        double blueSum = 0.0;
        double total = (double)(height * width);

        int means;

        int tb;
        int index;
        int row;
        int ta;
        int tr;
        int tg;
        for(means = 0; means < height; ++means) {


            for(tb = 0; tb < width; ++tb) {
                index = means * width + tb;
                row = inPixels[index] >> 24 & 255;
                ta = inPixels[index] >> 16 & 255;
                tr = inPixels[index] >> 8 & 255;
                tg = inPixels[index] & 255;
                redSum += (double)ta;
                greenSum += (double)tr;
                blueSum += (double)tg;
            }
        }

        means = (int)(redSum / total);
        System.out.println(" threshold average value = " + means);

        for(row = 0; row < height; ++row) {

            for(int col = 0; col < width; ++col) {
                index = row * width + col;
                ta = inPixels[index] >> 24 & 255;
                tr = inPixels[index] >> 16 & 255;
                tg = inPixels[index] >> 8 & 255;
                tb = inPixels[index] & 255;
                if (tr >= means) {
                    tb = 255;
                    tg = 255;
                    tr = 255;
                } else {
                    tb = 0;
                    tg = 0;
                    tr = 0;
                }

                outPixels[index] = ta << 24 | tr << 16 | tg << 8 | tb;
            }
        }

        Bitmap mBitmap = Bitmap.createBitmap(width, height, src.getConfig());
        mBitmap.setPixels(outPixels, 0, width, 0, 0, width, height);
        return mBitmap;
    }
}
